package com.mmall.service.impl;

import com.alipay.api.AlipayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.demo.trade.config.Configs;
import com.alipay.demo.trade.model.ExtendParams;
import com.alipay.demo.trade.model.GoodsDetail;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.service.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import com.alipay.demo.trade.utils.ZxingUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mmall.common.Const;
import com.mmall.common.ServerResponse;
import com.mmall.dao.*;
import com.mmall.pojo.*;
import com.mmall.service.OrderService;
import com.mmall.util.BigDecimalUtil;
import com.mmall.util.DateTimeUtil;
import com.mmall.util.FtpUtil;
import com.mmall.util.PropertiesUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;


@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Autowired
    private PayInfoMapper payInfoMapper;
    @Autowired
    private CartMapper cartMapper;
    @Autowired
    private ProductMapper productMapper;

    private static AlipayTradeService tradeService;

    private Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    public ServerResponse pay(Integer userId, Long orderNumber, String path) {
        Order order = orderMapper.selectByUserIdOrderNumber(userId, orderNumber);
        if (order == null) {
            return ServerResponse.createServerResponseByFailure("没有该订单!");
        }
        List<OrderItem> orderItemList = orderItemMapper.selectByOrderNumber(orderNumber);

        // (必填) 商户网站订单系统中唯一订单号，64个字符以内，只能包含字母、数字、下划线，
        // 需保证商户系统端不能重复，建议通过数据库sequence生成，
        String outTradeNo = orderNumber.toString();

        // (必填) 订单标题，粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费”
        String subject = "bingo商城交易信息";

        // (必填) 订单总金额，单位为元，不能超过1亿元
        // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】

        String totalAmount = order.getPayment().toString();

        // (可选) 订单不可打折金额，可以配合商家平台配置折扣活动，如果酒水不参与打折，则将对应金额填写至此字段
        // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
        String undiscountableAmount = "0";

        // 卖家支付宝账号ID，用于支持一个签约账号下支持打款到不同的收款账号，(打款到sellerId对应的支付宝账号)
        // 如果该字段为空，则默认为与支付宝签约的商户的PID，也就是appid对应的PID
        String sellerId = "";
        // 订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品2件共15.00元"
        String body = "购买商品3件共20.00元";

        // 商户操作员编号，添加此参数可以为商户操作员做销售统计
        String operatorId = "test_operator_id";

        // (必填) 商户门店编号，通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持
        String storeId = "test_store_id";

        // 业务扩展参数，目前可添加由支付宝分配的系统商编号(通过setSysServiceProv iderId方法)，详情请咨询支付宝技术支持
        ExtendParams extendParams = new ExtendParams();

        extendParams.setSysServiceProviderId("2088100200300400500");

        // 支付超时，定义为120分钟
        String timeoutExpress = "120m";

        // 商品明细列表，需填写购买商品详细信息，
        List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
        for (OrderItem orderItem : orderItemList) {
            GoodsDetail goodsDetail = new GoodsDetail();
            goodsDetail.setGoodsName(orderItem.getProductName());   //商品名称
            goodsDetail.setQuantity(orderItem.getQuantity());//商品数量
            goodsDetail.setPrice(orderItem.getCurrentUnitPrice().longValue());//商品单价
            goodsDetail.setGoodsId(orderItem.getProductId().toString());//商品id
            goodsDetailList.add(goodsDetail);
        }


        // 创建扫码支付请求builder，设置请求参数
        AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
                .setSubject(subject).setTotalAmount(totalAmount).setOutTradeNo(outTradeNo)
                .setUndiscountableAmount(undiscountableAmount).setSellerId(sellerId).setBody(body)
                .setOperatorId(operatorId).setStoreId(storeId).setExtendParams(extendParams)
                .setTimeoutExpress(timeoutExpress)
                .setNotifyUrl(PropertiesUtil.getProperty("alipay.callback.url"))//支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
                .setGoodsDetailList(goodsDetailList);

        Configs.init("zfbinfo.properties");

        /** 使用Configs提供的默认参数
         *  AlipayTradeService可以使用单例或者为静态成员对象，不需要反复new
         */
        tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();

        AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
        switch (result.getTradeStatus()) {
            case SUCCESS:
                logger.info("支付宝预下单成功: )");
                AlipayTradePrecreateResponse response = result.getResponse();
                dumpResponse(response);
                File file = new File(path);
                if (!file.exists()) {
                    file.setWritable(true);
                    file.mkdir();
                }
                String qrPath = String.format(path + "/qr-%s.png", response.getOutTradeNo());
                String fileName = String.format("/qr-%s.png", response.getOutTradeNo());
                ZxingUtils.getQRCodeImge(response.getQrCode(), 256, qrPath);
                File targetFile = new File(path, fileName);
                List<File> fileList = Lists.newArrayList(targetFile);
                try {
                    FtpUtil.uploadFile(fileList);
                } catch (IOException e) {
                    logger.error("二维码上传异常");
                }
                String qrUrl = PropertiesUtil.getProperty("ftp.server.http.prefix") + targetFile.getName();
                Map<String, String> resultMap = Maps.newHashMap();
                resultMap.put("qrUrl", qrUrl);
                return ServerResponse.createServerResponseBySuccess(resultMap);
            case FAILED:
                logger.error("支付宝预下单失败!!!");
                return ServerResponse.createServerResponseByFailure("支付宝预下单失败!!!");

            case UNKNOWN:
                logger.error("系统异常，预下单状态未知!!!");
                return ServerResponse.createServerResponseByFailure("系统异常，预下单状态未知!!!");

            default:
                logger.error("不支持的交易状态，交易返回异常!!!");
                return ServerResponse.createServerResponseByFailure("不支持的交易状态，交易返回异常!!!");
        }

    }

    private void dumpResponse(AlipayResponse response) {
        if (response != null) {
            logger.info(String.format("code:%s, msg:%s", response.getCode(), response.getMsg()));
            if (StringUtils.isNotEmpty(response.getSubCode())) {
                logger.info(String.format("subCode:%s, subMsg:%s", response.getSubCode(),
                        response.getSubMsg()));
            }
            logger.info("body:" + response.getBody());
        }
    }


    public ServerResponse payCallBack(Map<String, String> param) {
        String orderNumber = param.get("out_trade_no");//订单号
        String trade_no = param.get("trade_no");//支付宝交易号
        String trade_status = param.get("trade_status");

        Order order = orderMapper.selectByOrderNumber(Long.parseLong(orderNumber));
        if (order == null) {
            return ServerResponse.createServerResponseByFailure("非bingo商城订单");
        }

        //交易成功
        if (Const.AlipayCallBack.TRADE_SUCCESS.equals(trade_status)) {
            order.setStatus(Const.OrderStatusEnum.ORDER_SUCCESS.getCode());
            order.setPaymentTime(DateTimeUtil.strToDate(param.get("gmt_payment")));
            orderMapper.updateSelectiveByPrimaryKey(order);
        }
        PayInfo payInfo = new PayInfo();
        payInfo.setUserId(order.getUserId());
        payInfo.setOrderNo(Long.parseLong(orderNumber));
        payInfo.setPlatformStatus(trade_status);
        payInfo.setPayPlatform(Const.PayPlatformEnum.ZHIFUBAO.getCode());
        payInfo.setPlatformNumber(trade_no);
        payInfoMapper.insert(payInfo);
        return ServerResponse.createServerResponseBySuccess();

    }

    public ServerResponse queryOrderStatus(Integer userId, Long orderNumber) {
        Order order = orderMapper.selectByUserIdOrderNumber(userId, orderNumber);
        if (order == null) {
            return ServerResponse.createServerResponseByFailure();
        }
        return ServerResponse.createServerResponseBySuccess();

    }


    //生产订单编号
    public long getOrderNumber() {
        long orderNumber = System.currentTimeMillis();
        return orderNumber;

    }

    //创建订单
    public ServerResponse admitOrder(Integer userId, Integer shippingId) {

        List<Cart> cartItemList = cartMapper.selectCartByUserIdChecked(userId);

        ServerResponse<List<OrderItem>> serverResponse = this.getOrderItem(cartItemList, userId);
        List<OrderItem> orderItemList = (List<OrderItem>) serverResponse.getData();


        //插入订单
        Order order = new Order();
        order.setOrderNo(this.getOrderNumber());
        order.setUserId(userId);
        order.setStatus(Const.OrderStatusEnum.NOPAY.getCode());//设置订单状态没有支付
        BigDecimal payment = getOrderTotalPrice(orderItemList);
        order.setPayment(payment);     //  设置支付总金额
        order.setShippingId(shippingId);  //收获地址
        order.setPaymentType(Const.PaymentTypeEnum.ON_LINE.getCode()); //支付类型
        order.setPostage(0);    //运费
        int row = orderMapper.insert(order);
        if (row == 1) {
            return ServerResponse.createServerResponseBySuccess("创建订单成功");
        } else {
            return ServerResponse.createServerResponseBySuccess("创建订单失败");
        }
        //批量插入订单详情


        //将订单信息返回给前台页面
    }


    public BigDecimal getOrderTotalPrice(List<OrderItem> orderItemList) {
        BigDecimal totalPrice = new BigDecimal("0");
        for (OrderItem orderItem : orderItemList) {
            totalPrice = BigDecimalUtil.add(totalPrice.doubleValue(), orderItem.getTotalPrice().doubleValue());


        }
        return totalPrice;
    }

    //得到订单详情列表
    public ServerResponse<List<OrderItem>> getOrderItem(List<Cart> cartList, Integer userId) {
        List<OrderItem> orderItemList = Lists.newArrayList();
        if (cartList == null) {
            return ServerResponse.createServerResponseByFailure("购物车没有选择相关商品");
        }
        for (Cart cart : cartList) {
            Product product = productMapper.selectByPrimaryKey(cart.getProductId());
            OrderItem orderItem = new OrderItem();
            orderItem.setProductId(product.getId());
            orderItem.setProductName(product.getName());
            orderItem.setTotalPrice(BigDecimalUtil.sub(product.getPrice().doubleValue(), cart.getQuantity().doubleValue()));
            orderItem.setCurrentUnitPrice(product.getPrice());//设置付款是的价格。这个价格不是联动的
            orderItem.setProductImage(product.getMainImage());
            orderItem.setUserId(userId);
            orderItem.setQuantity(cart.getQuantity());
            orderItemList.add(orderItem);
        }
        return ServerResponse.createServerResponseBySuccess(orderItemList);
    }

    @Override
    public void closeOrder(int hour) {
        Date closeDateTime = DateUtils.addHours(new Date(), -hour);
        List<Order> orderList = orderMapper.selectOrderStatusByCreateTime(Const.OrderStatusEnum.NOPAY.getCode(), DateTimeUtil.DatetoStr(closeDateTime));
        for (Order order : orderList) {
            List<OrderItem> orderItems = orderItemMapper.selectByOrderNumber(order.getOrderNo());
            for (OrderItem orderItem : orderItems) {
                Integer productId = orderItem.getProductId();
                Product product = productMapper.selectByPrimaryKey(productId);
                product.setStock(product.getStock() + orderItem.getQuantity());
                productMapper.updateSelective(product);
            }
        }
    }
}
